home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’95 / ProcessBar™ / Code / Sources / floaters.c < prev    next >
Encoding:
Text File  |  1995-09-10  |  9.7 KB  |  303 lines  |  [TEXT/MMCC]

  1. // File "floaters.c" - 
  2.  
  3. #include <TextServices.h>
  4.  
  5. #include "floaters.h"
  6. #include "main.h"
  7.  
  8. // * ****************************************************************************** *
  9. // Global Declarations
  10.  
  11. extern GlobalsRec glob;
  12.  
  13. // * ****************************************************************************** *
  14. // * ****************************************************************************** *
  15.  
  16. WindowPtr NewFloater(Ptr wStorage, Rect *bounds, Str255 title, Boolean visFlag,
  17.         short wdefProc, WindowPtr behind, Boolean closeFlag, long refCon, long hotApp,
  18.         FloaterEventProcPtr eventHandler, FloaterCloseProcPtr closeHandler) {
  19.     short err=0;
  20.     Boolean myStorage = (wStorage) ? TRUE : FALSE;
  21.     WindowPtr win=0;
  22.     FloaterQElemPtr myQElem;
  23.     
  24.     if (myStorage) wStorage = NewPtr(sizeof(WindowRecord));
  25.     if (myStorage && !wStorage) return(0);
  26.     
  27.     err = NewServiceWindow(wStorage, bounds, title, FALSE, wdefProc, (WindowPtr) -1,
  28.             closeFlag, (ComponentInstance) kCurrentProcess, &win);
  29.     if (err) {
  30.         if (myStorage) DisposePtr(wStorage);
  31.         return(0);
  32.         }
  33.         
  34.     myQElem = (FloaterQElemPtr) NewPtrSys(sizeof(* myQElem));
  35.     if (! myQElem) {
  36.         if (win) CloseServiceWindow(win);
  37.         if (myStorage) DisposePtr(wStorage);
  38.         return(0);
  39.         }
  40.     myQElem->qLink = 0;
  41.     myQElem->qType = 0;
  42.     myQElem->hideMe = FALSE;
  43.     myQElem->hotApplication = hotApp;
  44.     myQElem->floatWindow = win;
  45.     myQElem->eventHandler = eventHandler;
  46.     myQElem->closeHandler = closeHandler;
  47.     Enqueue((QElem *) myQElem, &glob.allFloatWindows);
  48.  
  49.     SetWRefCon(win, refCon);
  50.     HiliteWindow(win, -1);
  51.     if (visFlag) ShowHide(win, -1);
  52.  
  53.     return(win);
  54.     }
  55.  
  56. // * ****************************************************************************** *
  57. // * ****************************************************************************** *
  58.  
  59. void CloseFloater(WindowPtr win) {
  60.     FloaterQElemPtr myQElem, qTail;
  61.     
  62.     // Get the window's QElem and release its memory
  63.     myQElem = GetOneFloater(win, TRUE);
  64.     if (myQElem) DisposePtr((Ptr) myQElem);
  65.     
  66.     ShowHide(win, -1);
  67.     CloseServiceWindow(win);
  68.  
  69.     UpdateFloater(0);
  70.     }
  71.  
  72. // * ****************************************************************************** *
  73. // * ****************************************************************************** *
  74.  
  75. void DisposeFloater(WindowPtr win) {
  76.     FloaterQElemPtr myQElem;
  77.     
  78.     // Get the window's QElem and release its memory
  79.     myQElem = GetOneFloater(win, TRUE);
  80.     if (myQElem) DisposePtr((Ptr) myQElem);
  81.     
  82.     ShowHide(win, -1);
  83.     CloseServiceWindow(win);
  84.     DisposePtr((Ptr) win);
  85.     
  86.     UpdateFloater(0);
  87.     }
  88.  
  89. // * ****************************************************************************** *
  90. // * ****************************************************************************** *
  91.  
  92. FloaterQElemPtr GetOneFloater(WindowPtr win, Boolean dequeueIt) {
  93.     FloaterQElemPtr myQElem;
  94.     
  95.     // Get the window's QElem and release its memory
  96.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead,
  97.             glob.allFloatWindows.qTail->qLink = 0; myQElem && 
  98.             (myQElem->floatWindow != win); myQElem = myQElem->qLink);
  99.  
  100.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  101.     return(myQElem);
  102.     }
  103.  
  104. // * ****************************************************************************** *
  105. // * ****************************************************************************** *
  106.  
  107. FloaterQElemPtr GetIndFloater(short index, Boolean dequeueIt) {
  108.     FloaterQElemPtr myQElem;
  109.     
  110.     if (index <= 0) return(0);
  111.     
  112.     // Get the window's QElem and release its memory
  113.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead,
  114.             glob.allFloatWindows.qTail->qLink = 0, index--; myQElem && index;
  115.             myQElem = myQElem->qLink, index--);
  116.  
  117.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  118.     return(myQElem);
  119.     }
  120.  
  121. // * ****************************************************************************** *
  122. // * ****************************************************************************** *
  123.  
  124. // If you have set the Hot Application, then this function checks whether that
  125. //   process is the front one and hides or shows the window as appropriate.
  126. Boolean ShowHideFloater(WindowPtr win) {
  127.     Boolean toHide, anyChanges=FALSE;
  128.     short index;
  129.     ProcessSerialNumber psn;
  130.     ProcessInfoRec pInfo;
  131.     FloaterQElemPtr myQElem;
  132.     
  133.     pInfo.processInfoLength = sizeof(pInfo);
  134.     pInfo.processName = 0;
  135.     pInfo.processAppSpec = 0;
  136.     
  137.     if (GetFrontProcess(&psn) || GetProcessInformation(&psn, &pInfo)) 
  138.         pInfo.processSignature = -1;
  139.  
  140.     if (! win) {
  141.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  142.                 myQElem = GetIndFloater(++index, FALSE)) {
  143.             win = myQElem->floatWindow;
  144.             if (! win) continue;
  145.  
  146.             toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  147.                     myQElem->hideMe || (myQElem->hotApplication && 
  148.                     (pInfo.processSignature != myQElem->hotApplication));
  149.             
  150.             if (! toHide && ! ((WindowPeek) win)->visible) {
  151.                 ShowHide(win, TRUE);
  152.                 anyChanges = TRUE;
  153.                 }
  154.               else if (toHide && ((WindowPeek) win)->visible) {
  155.                 ShowHide(win, FALSE);
  156.                 anyChanges = TRUE;
  157.                 }
  158.             }
  159.         }
  160.       else if (myQElem = GetOneFloater(win, FALSE)) {
  161.         toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  162.                 myQElem->hideMe || (myQElem->hotApplication && 
  163.                 (pInfo.processSignature != myQElem->hotApplication));
  164.         
  165.         if (! toHide && ! ((WindowPeek) win)->visible) {
  166.             ShowHide(win, TRUE);
  167.             anyChanges = TRUE;
  168.             }
  169.           else if (toHide && ((WindowPeek) win)->visible) {
  170.             ShowHide(win, FALSE);
  171.             anyChanges = TRUE;
  172.             }
  173.         }
  174.     return(anyChanges);
  175.     }
  176.  
  177. // * ****************************************************************************** *
  178. // * ****************************************************************************** *
  179.  
  180. void UpdateFloater(WindowPtr win) {
  181.     short index;
  182.     EventRecord theEvent;
  183.     FloaterQElemPtr myQElem;
  184.  
  185.     theEvent.what = updateEvt;
  186.     theEvent.when = TickCount();
  187.     theEvent.message = (long) win;
  188.     
  189.     if (! win) {
  190.         // Call the event handler for every floating window
  191.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  192.                 myQElem = GetIndFloater(++index, FALSE)) {
  193.             win = myQElem->floatWindow;
  194.             if (win && ! EmptyRgn(((WindowPeek) win)->updateRgn)) {
  195.                 theEvent.message = (long) win;
  196.                 if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  197.                 }
  198.             }
  199.         }
  200.       else if (myQElem = GetOneFloater(win, FALSE))
  201.         // Call the event handler for the indicated window
  202.         if (! EmptyRgn(((WindowPeek) win)->updateRgn))
  203.             if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  204.  
  205.     }
  206.  
  207. // * ****************************************************************************** *
  208. // * ****************************************************************************** *
  209.  
  210. void EventDispatchFloaters(EventRecord *theEvent, WindowPtr win) {
  211.     short index;
  212.     FloaterQElemPtr myQElem;
  213.  
  214.     if (! win) {
  215.         // Call the event handler for every floating window
  216.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  217.                 myQElem = GetIndFloater(++index, FALSE)) 
  218.             if (myQElem->eventHandler) 
  219.                 (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  220.         }
  221.       else if (myQElem = GetOneFloater(win, FALSE))
  222.         // Call the event handler for the indicated window
  223.         if (myQElem->eventHandler) 
  224.             (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  225.  
  226.     }
  227.  
  228.  
  229. // * ****************************************************************************** *
  230. // * ****************************************************************************** *
  231.  
  232. void CloseRemainingFloaters() {
  233.     FloaterQElemPtr myQElem;
  234.  
  235.     // For each tracked window, we call its close procedure - WE'RE QUITTING
  236.     //   Of course, you may find it necessary to add a "Save?" dialog, and escape
  237.     //   the quit sequence on a user cancel -- this code would need to be fixed.
  238.     while(myQElem = GetIndFloater(1, FALSE)) 
  239.         if (myQElem->closeHandler) (*myQElem->closeHandler)(myQElem->floatWindow);
  240.           else DisposeFloater(myQElem->floatWindow);
  241.     }
  242.  
  243. // * ****************************************************************************** *
  244. // * ****************************************************************************** *
  245.  
  246. Boolean GetFloaterEvent(EventRecord *theEvent) {
  247.     Boolean floaterEvent = FALSE;
  248.     short err=0, index;
  249.     EvQEl *fwdEvent=0;
  250.     FloaterQElemPtr myQElem;
  251.     
  252.     // Extract any forwarded events... and treat them as normal
  253.     if (fwdEvent = (EvQEl *) glob.forwardedEvents.qHead)
  254.         err = Dequeue((QElemPtr) fwdEvent, &glob.forwardedEvents);
  255.  
  256.     if (fwdEvent && !err) {
  257.         BlockMove(&fwdEvent->evtQWhat, theEvent, sizeof(EventRecord));
  258.         DisposePtr((Ptr) fwdEvent);
  259.         
  260.         // DONT ZERO IT OUT - The pointer indicates that we are
  261.         //   handling an event for a Floater window. 
  262.  
  263.         floaterEvent = TRUE;
  264.         }
  265.         
  266.     return(floaterEvent);
  267.     }
  268.  
  269. // * ****************************************************************************** *
  270. // * ****************************************************************************** *
  271.  
  272. // Thanks to Dair Grant (dair.grant@ucl.ac.uk) - I now check the MBarHeight
  273. //   of the *Front* process, and remember (via globals) when executing in bkgd.
  274.  
  275. // Remember that this function must be called from within that app's context!
  276. Boolean TestScreenSaver() {
  277.     Boolean inFront=FALSE;
  278.     long result;
  279.     ProcessSerialNumber frontPSN, curPSN;
  280.  
  281.     glob.blockFloats = FALSE;
  282.  
  283.     // Most screensavers should register themselves this way
  284.     if (!Gestalt('SAVR', &result) && (result & 0x02)) glob.blockFloats = TRUE;
  285.       else {
  286.         // We also want to hide ourselves if the foreground application
  287.         // has hidden the menu bar, since this implies they're taking
  288.         // over the whole screen (and they probably don't want us visible).
  289.         
  290.         // Only when we are executing in the foreground app can we check the
  291.         //   height of the menubar. When the front process has hidden its
  292.         //   menubar, then we set a global flag to enact our desires.
  293.         if (!GetFrontProcess(&frontPSN) && !GetCurrentProcess(&curPSN))
  294.             if (SameProcess(&frontPSN, &curPSN, &inFront)) inFront = FALSE;
  295.         
  296.         if (inFront && (GetMBarHeight() == 0)) glob.blockFloats = TRUE;
  297.         }
  298.     
  299.     return(glob.blockFloats);
  300.     }
  301.  
  302.  
  303.